/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights
 * reserved. <a>http://www.cqcis.com</a>
 */
package com.cqcis.uip.base.framework.service.impl;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

import org.apache.mina.common.ExecutorThreadModel;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import com.cqcis.uip.base.framework.FrameworkConstants;
import com.cqcis.uip.base.framework.codec.impl.DefaultProtocolObjectDecoder;
import com.cqcis.uip.base.framework.codec.impl.DefaultProtocolObjectEncoder;
import com.cqcis.uip.base.framework.codec.text.HttpProtocolDecoder;
import com.cqcis.uip.base.framework.codec.text.HttpProtocolEncoder;
import com.cqcis.uip.base.framework.codec.text.TextProtocolDecoder;
import com.cqcis.uip.base.framework.codec.text.TextProtocolEncoder;
import com.cqcis.uip.base.framework.common.HttpParam;
import com.cqcis.uip.base.framework.utils.ByteBuffer;
import com.cqcis.uip.base.framework.utils.LogServiceThreadPoolExecutor;
import com.cqcis.uip.base.framework.utils.LogServiceThreadPoolExecutor.LogThreadPoolExecutor;

/**
 * telnet终端实现
 * 
 * @author huangmy
 * @date   2008-4-22
 */
public class TelnetConsoleSupport implements BundleActivator {
	private SocketAcceptorConfig config;
	private SocketAcceptor telnetAcceptor; // telnet server
	private TelnetConsoleServiceImpl telnetHandler;
	private LogThreadPoolExecutor socketThreadModelExecutor;
	
    public void start(BundleContext context) throws Exception {
		config = new SocketAcceptorConfig();
		config.setBacklog(30);
		config.setReuseAddress(true);
		config.setDisconnectOnUnbind(true);
		telnetAcceptor = new SocketAcceptor();
		
		ExecutorThreadModel etm = ExecutorThreadModel.getInstance("Telnet-Console-ServiceSupport"); // 默认线程模型
		
		this.socketThreadModelExecutor = (LogThreadPoolExecutor)LogServiceThreadPoolExecutor.getLogExecutor(4, 
				12, 120, null, null, "Telnet-Console-ServiceSupport");
		etm.setExecutor(this.socketThreadModelExecutor);
		
		// 设置
		config.setThreadModel(etm);
				
		DefaultProtocolObjectDecoder decodec = new DefaultProtocolObjectDecoder();
		final HttpProtocolDecoder httpDecoder = new HttpProtocolDecoder();
		TextProtocolDecoder decoder = new TextProtocolDecoder() {
			@Override
			public Object decode(ByteBuffer buffer) throws Exception {
				IoSession session = buffer.getSession();
				if (session.getAttribute(FrameworkConstants.CLUSTER_SWITCH) != null) {
					// 转入http协议
					return httpDecoder.decode(buffer);
				}
				return super.decode(buffer);
			}
		};
		decoder.setPrintLog(false);
		List<String> prompts = new ArrayList<String>();
		prompts.add("uip>");
		prompts.add("\n");
		decoder.setLinePrompt(prompts);
		decodec.setDecoder(decoder);
		
		DefaultProtocolObjectEncoder encodec = new DefaultProtocolObjectEncoder();
		final HttpProtocolEncoder httpEncoder = new HttpProtocolEncoder();
		TextProtocolEncoder encoder = new TextProtocolEncoder() {
			@Override
			public ByteBuffer encode(Object message) throws Exception {	
				ByteBuffer buf = null;
				try {
					if (message instanceof HttpParam) {
						buf = httpEncoder.encode(message);
					} else {
				        buf = super.encode(message);
					}
				} catch (Exception e) {
					return ByteBuffer.allocate(4).setAutoExpand(true).flip();
				}
				return buf;
			}
		};
		encoder.setPrintLog(false);
		encodec.setEncoder(encoder);
		
		config.getFilterChain().addLast("ObjectReadWriteFilter", 
				new ProtocolCodecFilter(encodec, decodec));
				
		telnetHandler = new TelnetConsoleServiceImpl(context, this.socketThreadModelExecutor);
		telnetHandler.start();
		int port = 8081;
		try {
			port = Integer.parseInt(System.getProperty("uip.telnet.port", "8081"));
		} catch (Exception e) {			
		}
		
		telnetAcceptor.bind(new InetSocketAddress(port), telnetHandler, config);
	}
	
	public void stop(BundleContext context) throws Exception {
		if (telnetAcceptor != null) {
			telnetAcceptor.unbindAll();
		}
		
		if (telnetHandler != null) {
			telnetHandler.stop();
		}
		
		if (socketThreadModelExecutor != null) {
			socketThreadModelExecutor.shutdown();
		}
	}
}
